
#if {$tcl_interactive} {
         
    #package require Tk  
    #package require BLT
    #load /usr/local/lib/libspice.so
    #package require spice
#    package require tclreadline
#    ::tclreadline::Loop

#}

# NETWORK(instname) = { term0, term1, term2, ... }
array unset NETWORK
array unset INPINs
array unset OUTPINs
array unset INSTs
array unset NET

array unset 3D_CUBE


#read TPR 3d placement file
proc read_3d_placement_file {FILE {CG_ENABLE 0} } {
    
    global 3D_CUBE
    
    puts "read_placement_file $FILE"

    set fp [open $FILE r]

    set file_data [read $fp]

    set data [split $file_data "\n"]

    set maxX 0
    set maxY 0
    set maxZ 0
    set id 0

    foreach line $data {
        
        if {[regexp {(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\S+} $line junk name x y z]} {
            
            
            if { $x<=$maxX && $y<=$maxY && $z<=$maxZ } {
                
                set id "$x\_$y\_$z"
                #puts "bb: $id"
                if {[info exists 3D_CUBE($id)]} {
                    set 3D_CUBE($id) $name
                } else {
                    puts "Error @ read_3d_placement_file"
                    puts "  Can not find $id in cube"
                    return;
                }
                    
            } else {
                
                puts "Error @ read_3d_placement_file"
                puts "  (x,y,z) execeeds (maxX,maxY,maxZ)"
                puts "  ($x,$y,$z) vs ($maxX,$maxY,$maxZ)"
                return;

            }

        } elseif {[regexp {Array size: (\d+) x (\d+) x (\d+) logic blocks} $line junk maxX maxY maxZ]} {
            #puts "$maxX $maxY $maxZ"
            incr maxX
            incr maxY
            #puts "$maxX $maxY $maxZ"
            # Z
            for {set k 0} {$k<=$maxZ} {incr k} { 
                # X
                for {set i 0} {$i<=$maxX} {incr i} {
                    # Y
                    for {set j 0} {$j<=$maxY} {incr j} {
                
                        set id "$i\_$j\_$k"
                        set 3D_CUBE($id) 0
                        #puts "aa: $id"
                    
                    }
                }
            }

        }
    }

    foreach idx [array names 3D_CUBE] {
        #puts "$idx $3D_CUBE($idx)"
        set loc [split $idx "_"]
        set x [lindex $loc 0]
        set y [lindex $loc 1]
        set z [lindex $loc 2]

        if {$3D_CUBE($idx) != 0} {
            #CG3D_ADDCLB $3D_CUBE($idx) $x $y $z

            if {$CG_ENABLE == 1} { CG3D_SETCLBLOC $3D_CUBE($idx) $x $y $z }
            bs_set_cell_loc $3D_CUBE($idx) $x $y $z
        }
    }
    #CG3D_FLUSH

    close $fp
}

#read TPR netlist file
proc read_net_file {FILE {CG_ENABLE 0}} {
    
    global NETWORK
    global INPINs
    global OUTPINs

    puts "read_net_file $FILE"

    set fp [open $FILE r]

    set file_data [read $fp]
    
    #remove redudent space
    set new_file_data [string map {" \n" "\n"} $file_data]
    set data [split $new_file_data "\n"]

    set inst ""
    set parse_state 0

    foreach line $data {
        
        if {[regexp {.input\s+(\S+)} $line junk inst]} {
            set parse_state 0
            set INPINs($inst) 0
            #puts "input: $inst"
            #set INPINs($inst) 0
            #set NETWORK($inst) [list]
            #puts "bs_addcell $inst CLB"
            if {$CG_ENABLE == 1} { CG3D_ADDCLB $inst 0.0 0.0 0.0 }
            bs_addcell $inst IOIN

        } elseif {[regexp {.output\s+(\S+)} $line junk inst]} {
            set parse_state 1
            set OUTPINs($inst) 0
            #puts "bs_addcell $inst CLB"

            if {$CG_ENABLE == 1} { CG3D_ADDCLB $inst 0.0 0.0 0.0 }
            bs_addcell $inst IOOUT

        } elseif {[regexp {.clb\s+(\S+)} $line junk inst]} {
            set parse_state 2
            #puts "bs_addcell $inst CLB"

            if {$CG_ENABLE == 1} { CG3D_ADDCLB $inst 0.0 0.0 0.0 }
            bs_addcell $inst CLB

        } elseif {[regexp {pinlist: ([ A-Za-z0-9\[\]_]+)} $line junk pins]} {
            #puts "    AAA $pins"

            #store inst connection
            if {$parse_state == 2} {
                set pinlst [split $pins " "]
                set clk_idx [expr [llength $pinlst]-1]
                
                set outpin_idx [expr [llength $pinlst]-2]
                set outpin [lindex $pinlst $outpin_idx]
                
                if { [string compare $outpin "open"] == 0 } {
                    puts "WARNING: found floating load in $inst"
                    return
                }

                for {set i 0} {$i<$outpin_idx} {incr i} {
                    
                    set driver [lindex $pinlst $i]

                    if { [string compare $driver "open"] == 0 } {
                        continue
                    }

                    if {![info exists NETWORK($driver)]} {
                        set NETWORK($driver) [list $outpin]
                        #puts "A $driver $NETWORK($driver)"
                    } else {
                        lappend NETWORK($driver) $outpin
                        #puts "B $driver $NETWORK($driver)"
                    }
                }
            # store output connection
            } elseif {$parse_state == 1} {
                if {![info exists NETWORK($pins)]} {
                    set NETWORK($pins) [list $inst]
                    #puts "A $driver $NETWORK($driver)"
                } else {
                    lappend NETWORK($pins) $inst
                    #puts "B $driver $NETWORK($driver)"
                }
            }
        }
    }

    # draw lines
#    foreach i [array names NETWORK] {
#        
#        if {$CG_ENABLE == 1} { CG3D_ADDCLB $i 0.0 0.0 0.0}
#        
#        foreach j $NETWORK($i) {
#            
#            if {$CG_ENABLE == 1} { CG3D_ADDEDGE $i $j }
#            #puts "bs_addfanout $i $j"
#            bs_addedge $i $j
#        }
#    }
    close $fp
}

# read routing file
proc read_3d_routing_file {FILE {CG_ENABLE 0} } {
    
    puts "read_routing_file $FILE"

    global NET

    array unset NET
    puts "  reset NET..."

    set fp [open $FILE r]

    set file_data [read $fp]
    
    set data [split $file_data "\n"]
    set netid 0
    set netname 0

    foreach line $data {
        #puts $line
        if {[regexp {Net\s+(\S+)\s+\((\S+)\)} $line junk netid netname]} {
            #puts "$netid $netname"
            set NET($netname) [list]
        }

        if {[regexp {(SOURCE|CHANX|CHANY|CHANZ|TDM|SINK)\s+\((\d+),(\d+),(\d+)\)\s+\S+\s+(\d+)} $line junk type x y z track]} {
            #puts "$type $x $y $z $track"
            lappend NET($netname) [list $type $x $y $z $track]
        }
    }
    close $fp

    foreach idx [array names NET] {
        puts "$idx $NET($idx)"
    }
}

# draw net
proc draw_net_by_name {NETNAME COLOR} {
    global NET

    if {[info exists NET($NETNAME)]} {
        foreach seg $NET($NETNAME) {
            #puts "CG3D_ADD_NETSEG $seg"
            set data [split $seg " "]
            CG3D_ADD_NETSEG [lindex $data 0] [lindex $data 1] [lindex $data 2] [lindex $data 3] [lindex $data 4]
        }
    } else {
        puts "Error @ read_3d_placement_file"
        puts "  Can not find $NETNAME"
        return false
    }
    return true
}

# 
proc read_wns_path {FILE {CG_ENABLE 0}} {
    
    puts "read_wns_path $FILE"

    set fp [open $FILE r]
    set file_data [read $fp]
    set data [split $file_data "\n"]

    foreach line $data {
        #block(i_7_) INPAD_OPIN 4 0 3 arr=0.000000
        if {[regexp {block\((\S+)\)\s+(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\S+} $line junk clb clbType x y z]} {
            puts "$clb $clbType $x $y $z"
            CG3D_ADDCLB $clb $x $y $z
        } elseif {[regexp {Net\s+\d+\s+\((\S+)\)} $line junk net]} {
            #draw_net_by_name $net A
        } elseif {[regexp {(SOURCE|CHANX|CHANY|CHANZ|TDM|SINK)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+\S+} $line junk rrType x y z track]} {
            #puts "$rrType $x $y $z $track"
            CG3D_ADD_NETSEG $rrType $x $y $z $track 1.0 0.0 0.0
        }

    }

    close $fp

}

# launch UI
proc launch_ui {} {
    exec ~/bin/3DDrawing > /tmp/3DDrawing.log &
}

